package tool

import (
	"bytes"
	"errors"
	"image"
	"image/color"
	"image/draw"
	"image/gif"
	_ "image/gif"
	"image/jpeg"
	"image/png"
	_ "image/png"
)

var (
	NotSupportImage = errors.New("NotSupportImage")
)

const (
	RgbaMax = 255
)

func CompressImage(imageData []byte, quality int) []byte {

	decode, format, err := image.Decode(bytes.NewReader(imageData))
	if err != nil {
		return imageData
	}
	buf := bytes.Buffer{}
	switch format {
	case "jpeg":
		err := jpeg.Encode(&buf, decode, &jpeg.Options{Quality: quality})
		if err != nil {
			return imageData
		}
		return buf.Bytes()
	case "png":
		rgba := image.NewRGBA(decode.Bounds())
		draw.Draw(rgba, rgba.Bounds(), &image.Uniform{C: color.White}, image.Point{}, draw.Src)
		draw.Draw(rgba, rgba.Bounds(), decode, decode.Bounds().Min, draw.Over)
		err := jpeg.Encode(&buf, rgba, &jpeg.Options{Quality: quality})
		if err != nil {
			return imageData
		}
		return buf.Bytes()
	case "gif":
		err := gif.Encode(&buf, decode, nil)
		if err != nil {
			return imageData
		}
		return buf.Bytes()
	default:
		return imageData
	}
}

// ReverseImageColor 图片颜色反转
func ReverseImageColor(imageData []byte) []byte {
	decode, format, err := image.Decode(bytes.NewReader(imageData))
	if err != nil {
		return imageData
	}
	buf := bytes.Buffer{}
	dell := ColorDell(decode, ReverseColor)
	switch format {
	case "jpeg":
		err := jpeg.Encode(&buf, dell, &jpeg.Options{Quality: 100})
		if err != nil {
			return imageData
		}
		return buf.Bytes()
	case "png":
		rgba := image.NewRGBA(dell.Bounds())
		draw.Draw(rgba, rgba.Bounds(), &image.Uniform{C: color.White}, image.Point{}, draw.Src)
		draw.Draw(rgba, rgba.Bounds(), dell, dell.Bounds().Min, draw.Over)
		err := jpeg.Encode(&buf, rgba, &jpeg.Options{Quality: 100})
		if err != nil {
			return imageData
		}
		return buf.Bytes()
	case "gif":
		err := gif.Encode(&buf, dell, nil)
		if err != nil {
			return imageData
		}
		return buf.Bytes()
	default:
		return imageData
	}
}

// GrayImageColor 图片黑白
func GrayImageColor(imageData []byte) []byte {
	decode, format, err := image.Decode(bytes.NewReader(imageData))
	if err != nil {
		return imageData
	}
	buf := bytes.Buffer{}
	dell := ColorDell(decode, GrayColor)
	switch format {
	case "jpeg":
		err := jpeg.Encode(&buf, dell, &jpeg.Options{Quality: 100})
		if err != nil {
			return imageData
		}
		return buf.Bytes()
	case "png":
		rgba := image.NewRGBA(dell.Bounds())
		draw.Draw(rgba, rgba.Bounds(), &image.Uniform{C: color.White}, image.Point{}, draw.Src)
		draw.Draw(rgba, rgba.Bounds(), dell, dell.Bounds().Min, draw.Over)
		err := jpeg.Encode(&buf, rgba, &jpeg.Options{Quality: 100})
		if err != nil {
			return imageData
		}
		return buf.Bytes()
	case "gif":
		err := gif.Encode(&buf, dell, nil)
		if err != nil {
			return imageData
		}
		return buf.Bytes()
	default:
		return imageData
	}
}

func GetImage(imageData []byte) ([]byte, string, error) {

	decode, format, err := image.Decode(bytes.NewReader(imageData))
	if err != nil {
		return imageData, "", err
	}
	buf := bytes.Buffer{}
	switch format {
	case "jpeg":
		err := jpeg.Encode(&buf, decode, &jpeg.Options{Quality: 100})
		if err != nil {
			return imageData, "", err
		}
		return buf.Bytes(), "jpg", nil
	case "png":
		err := png.Encode(&buf, decode)
		if err != nil {
			return imageData, "", err
		}
		return buf.Bytes(), "png", nil
	case "gif":
		err := gif.Encode(&buf, decode, nil)
		if err != nil {
			return imageData, "", err
		}
		return buf.Bytes(), "gif", nil
	default:
		return imageData, "", NotSupportImage
	}
}
